package com.ssy.lingxi.member.merchant.serviceimpl.web;

import com.ssy.lingxi.common.constant.basic.EnableDisableStatus;
import com.ssy.lingxi.common.constant.manage.ShopTypeEnum;
import com.ssy.lingxi.common.constant.order.OrderTypeEnum;
import com.ssy.lingxi.common.model.dto.UserLoginCacheDTO;
import com.ssy.lingxi.common.response.PageData;
import com.ssy.lingxi.common.response.ResponseCode;
import com.ssy.lingxi.common.response.Wrapper;
import com.ssy.lingxi.common.utils.DateTimeUtil;
import com.ssy.lingxi.member.merchant.api.constant.TradeCommentHistoryStatusEnum;
import com.ssy.lingxi.member.merchant.config.ServiceConfig;
import com.ssy.lingxi.member.merchant.entity.MemberOrderCommentDO;
import com.ssy.lingxi.member.merchant.entity.MemberOrderProductCommentDO;
import com.ssy.lingxi.member.merchant.entity.MemberRelationDO;
import com.ssy.lingxi.member.merchant.entity.MemberTradeCommentHistoryDO;
import com.ssy.lingxi.member.merchant.api.constant.MemberRelationTypeEnum;
import com.ssy.lingxi.member.merchant.model.constant.MemberTradeTypeEnum;
import com.ssy.lingxi.member.merchant.model.vo.comment.request.*;
import com.ssy.lingxi.member.merchant.model.vo.comment.response.*;
import com.ssy.lingxi.member.merchant.model.vo.lifecycle.request.CommonIdVO;
import com.ssy.lingxi.member.merchant.model.vo.maintenance.response.MemberDetailCreditCommentSummaryVO;
import com.ssy.lingxi.member.merchant.model.vo.maintenance.response.MemberDetailCreditTradeHistoryVO;
import com.ssy.lingxi.member.merchant.repository.MemberOrderCommentRepository;
import com.ssy.lingxi.member.merchant.repository.MemberOrderProductCommentRepository;
import com.ssy.lingxi.member.merchant.repository.MemberRelationRepository;
import com.ssy.lingxi.member.merchant.repository.MemberTradeCommentHistoryRepository;
import com.ssy.lingxi.member.merchant.service.base.IBaseMemberCreditAsyncService;
import com.ssy.lingxi.member.merchant.service.base.IBaseMemberLevelAsyncService;
import com.ssy.lingxi.member.merchant.service.feign.IPlatformManageFeignService;
import com.ssy.lingxi.member.merchant.service.feign.IReportFeignService;
import com.ssy.lingxi.member.merchant.service.web.IMemberCommentService;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.persistence.criteria.Predicate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 会员评论服务接口实现类
 * @author 姚梓聪
 * @version 2.0.0
 * @date 2020-10-23
 */
@Service
public class MemberCommentServiceImpl extends BaseMemberCommentServiceImpl implements IMemberCommentService {

    private static final Logger log = LoggerFactory.getLogger(MemberCommentServiceImpl.class);

    @Resource
    private MemberTradeCommentHistoryRepository memberTradeCommentHistoryRepository;

    @Resource
    private MemberRelationRepository relationRepository;

    @Resource
    private IPlatformManageFeignService platformManageFeignService;

    @Resource
    private IBaseMemberLevelAsyncService memberLevelAsyncService;

    @Resource
    private IBaseMemberCreditAsyncService memberCreditAsyncService;

    @Resource
    private IReportFeignService reportFeignService;

    @Resource
    private MemberOrderCommentRepository memberOrderCommentRepository;

    @Resource
    private MemberOrderProductCommentRepository memberOrderProductCommentRepository;

    /**
     * 交易能力 - 会员评价管理 - 订单商品评价详情
     *
     * @param loginUser 登录用户信息
     * @param memberTradeTypeEnum 评价方角色枚举 1-供应会员，2-采购会员
     * @param commonIdVO 接口参数
     * @return 查询结果
     */
    @Override
    public Wrapper<MemberOrderCommentDetailVO> getMemberOrderCommentDetail(UserLoginCacheDTO loginUser, MemberTradeTypeEnum memberTradeTypeEnum, CommonIdVO commonIdVO) {
        // 订单
        MemberOrderCommentDO memberOrderCommentDO = memberOrderCommentRepository.findById(commonIdVO.getId()).orElse(null);
        if (Objects.isNull(memberOrderCommentDO)) {
            return Wrapper.fail(ResponseCode.MC_MS_RECORDS_DON_T_EXIST);
        }

        // 会员数据关联
        if (MemberTradeTypeEnum.BUYER.equals(memberTradeTypeEnum)) {
            if (!memberOrderCommentDO.getBuyerMemberId().equals(loginUser.getMemberId()) || !memberOrderCommentDO.getBuyerRoleId().equals(loginUser.getMemberRoleId())) {
                return Wrapper.fail(ResponseCode.MC_MS_RECORDS_DON_T_EXIST);
            }
        } else {
            if (!memberOrderCommentDO.getVendorMemberId().equals(loginUser.getMemberId()) || !memberOrderCommentDO.getVendorRoleId().equals(loginUser.getMemberRoleId())) {
                return Wrapper.fail(ResponseCode.MC_MS_RECORDS_DON_T_EXIST);
            }
        }

        // 订单商品
        List<MemberOrderProductCommentDO> memberOrderProductCommentDOList = memberOrderProductCommentRepository.findAllByOrderId(commonIdVO.getId());
        if (CollectionUtils.isEmpty(memberOrderProductCommentDOList)) {
            return Wrapper.fail(ResponseCode.MC_MS_RECORDS_DON_T_EXIST);
        }

        // 订单商品评价记录
        List<MemberTradeCommentHistoryDO> memberTradeCommentHistoryDOList = memberTradeCommentHistoryRepository.findAllByOrderIdAndTradeType(commonIdVO.getId(), memberTradeTypeEnum.getTypeEnum());
        Map<Long, MemberTradeCommentHistoryDO> productCommentMap = memberTradeCommentHistoryDOList.stream().collect(Collectors.toMap(MemberTradeCommentHistoryDO::getProductId, e -> e, (e1, e2) -> e2));

        // 汇总订单商品和评价数据
        List<MemberOrderProductCommentVO> orderProductCommentList = memberOrderProductCommentDOList.stream().map(e -> {
            // 从构造的映射中取, 可能为空
            MemberTradeCommentHistoryDO commentHistoryDO = productCommentMap.get(e.getProductId());
            MemberOrderProductCommentVO memberOrderProductCommentVO = new MemberOrderProductCommentVO();
            memberOrderProductCommentVO.setOrderProductId(e.getId());
            memberOrderProductCommentVO.setProductId(e.getProductId());
            memberOrderProductCommentVO.setSkuId(e.getSkuId());
            memberOrderProductCommentVO.setProductNo(e.getProductNo());
            memberOrderProductCommentVO.setName(e.getName());
            memberOrderProductCommentVO.setCategory(e.getCategory());
            memberOrderProductCommentVO.setBrand(e.getBrand());
            memberOrderProductCommentVO.setSpec(e.getSpec());
            memberOrderProductCommentVO.setUnit(e.getUnit());
            memberOrderProductCommentVO.setLogo(e.getLogo());
            memberOrderProductCommentVO.setPrice(e.getPrice());
            memberOrderProductCommentVO.setQuantity(e.getQuantity());
            memberOrderProductCommentVO.setAmount(e.getAmount());
            memberOrderProductCommentVO.setStar(Optional.ofNullable(commentHistoryDO).map(MemberTradeCommentHistoryDO::getStar).orElse(null));
            memberOrderProductCommentVO.setComment(Optional.ofNullable(commentHistoryDO).map(MemberTradeCommentHistoryDO::getComment).orElse(""));
            memberOrderProductCommentVO.setPics(Optional.ofNullable(commentHistoryDO).map(MemberTradeCommentHistoryDO::getPics).orElse(Collections.emptyList()));
            memberOrderProductCommentVO.setCommentStatus(MemberTradeTypeEnum.BUYER.getTypeEnum().equals(memberTradeTypeEnum.getTypeEnum()) ? e.getBuyerCommentStatus() : e.getVendorCommentStatus());
            return memberOrderProductCommentVO;
        }).collect(Collectors.toList());

        // 返回实体
        MemberOrderCommentDetailVO memberOrderCommentDetailVO = new MemberOrderCommentDetailVO();
        memberOrderCommentDetailVO.setOrderId(memberOrderCommentDO.getId());
        memberOrderCommentDetailVO.setOrderNo(memberOrderCommentDO.getOrderNo());
        memberOrderCommentDetailVO.setOrderType(memberOrderCommentDO.getOrderType());
        memberOrderCommentDetailVO.setOrderTypeName(OrderTypeEnum.getNameByCode(memberOrderCommentDO.getOrderType()));
        memberOrderCommentDetailVO.setCreateTime(DateTimeUtil.formatDateTime(memberOrderCommentDO.getCreateTime()));
        if (!MemberTradeTypeEnum.BUYER.getTypeEnum().equals(memberTradeTypeEnum.getTypeEnum())) {
            memberOrderCommentDetailVO.setMemberId(memberOrderCommentDO.getBuyerMemberId());
            memberOrderCommentDetailVO.setRoleIdId(memberOrderCommentDO.getBuyerRoleId());
            memberOrderCommentDetailVO.setMemberName(memberOrderCommentDO.getBuyerMemberName());
        } else {
            memberOrderCommentDetailVO.setMemberId(memberOrderCommentDO.getVendorMemberId());
            memberOrderCommentDetailVO.setRoleIdId(memberOrderCommentDO.getVendorRoleId());
            memberOrderCommentDetailVO.setMemberName(memberOrderCommentDO.getVendorMemberName());
        }
        memberOrderCommentDetailVO.setShopId(memberOrderCommentDO.getShopId());
        memberOrderCommentDetailVO.setShopName(memberOrderCommentDO.getShopName());
        memberOrderCommentDetailVO.setShopName(memberOrderCommentDO.getShopName());
        memberOrderCommentDetailVO.setOrderProductCommentList(orderProductCommentList);

        return Wrapper.success(memberOrderCommentDetailVO);
    }

    /**
     * 交易能力-会员评价管理-发表评价
     *
     * @param loginUser 登录用户信息
     * @param memberTradeTypeEnum 评价方角色枚举 1-供应会员，2-采购会员
     * @param commentSubmitVO 接口参数
     * @return 查询结果
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public Wrapper<Void> submitMemberTradeComment(UserLoginCacheDTO loginUser, MemberTradeTypeEnum memberTradeTypeEnum, MemberTradeCommentSubmitVO commentSubmitVO) {
        // 订单
        MemberOrderCommentDO memberOrderCommentDO = memberOrderCommentRepository.findById(commentSubmitVO.getOrderId()).orElse(null);
        if (Objects.isNull(memberOrderCommentDO)) {
            return Wrapper.fail(ResponseCode.MC_MS_RECORDS_DON_T_EXIST);
        }

        // 会员数据关联
        if (MemberTradeTypeEnum.BUYER.equals(memberTradeTypeEnum)) {
            if (!memberOrderCommentDO.getBuyerMemberId().equals(loginUser.getMemberId()) || !memberOrderCommentDO.getBuyerRoleId().equals(loginUser.getMemberRoleId())) {
                return Wrapper.fail(ResponseCode.MC_MS_RECORDS_DON_T_EXIST);
            }
        } else {
            if (!memberOrderCommentDO.getVendorMemberId().equals(loginUser.getMemberId()) || !memberOrderCommentDO.getVendorRoleId().equals(loginUser.getMemberRoleId())) {
                return Wrapper.fail(ResponseCode.MC_MS_RECORDS_DON_T_EXIST);
            }
        }

        return this.baseSubmitMemberTradeComment(memberTradeTypeEnum, memberOrderCommentDO, commentSubmitVO.getCommentSubmitDetailList(), true);
    }

    /**
     * 系统定时自动评价
     *
     * @param memberTradeTypeEnum 评价方角色枚举 1-供应会员，2-采购会员
     * @param commentSubmitVO 接口参数
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void submitAutoMemberTradeComment(MemberTradeTypeEnum memberTradeTypeEnum, MemberOrderCommentDO memberOrderCommentDO, MemberTradeCommentSubmitVO commentSubmitVO) {
        this.baseSubmitMemberTradeComment(memberTradeTypeEnum, memberOrderCommentDO, commentSubmitVO.getCommentSubmitDetailList(), false);
    }

    /**
     * 交易能力 - 会员评价管理 - 收到评价分页列表
     * 如果采购会员查看, 评价方角色是供应会员
     * 如果供应会员查看, 评价方角色是采购会员
     *
     * @param loginUser 登录用户信息
     * @param memberTradeTypeEnum 评价方角色枚举 1-供应会员，2-采购会员
     * @param pageVO 接口参数
     * @return 查询结果
     */
    @Override
    public Wrapper<PageData<MemberReceiveTradeCommentPageVO>> pageMemberReceiveTradeCommentHistory(UserLoginCacheDTO loginUser, MemberTradeTypeEnum memberTradeTypeEnum, MemberReceiveTradeCommentQueryVO pageVO) {
        Pageable page = PageRequest.of(pageVO.getCurrent() - 1, pageVO.getPageSize(), Sort.by("dealTime").descending());

        Page<MemberTradeCommentHistoryDO> pageList = memberTradeCommentHistoryRepository.findAll((Specification<MemberTradeCommentHistoryDO>) (root, query, cb) -> {
            List<Predicate> predicateList = new ArrayList<>();
            predicateList.add(cb.equal(root.get("subMemberId"), loginUser.getMemberId()));
            predicateList.add(cb.equal(root.get("subRoleId"), loginUser.getMemberRoleId()));
            predicateList.add(cb.equal(root.get("tradeType"), memberTradeTypeEnum.getTypeEnum()));
            if (Objects.nonNull(pageVO.getStar())) {
                predicateList.add(cb.equal(root.get("star"), pageVO.getStar()));
            }
            if (Objects.nonNull(pageVO.getDealTimeStart())) {
                predicateList.add(cb.greaterThanOrEqualTo(root.get("dealTime"), pageVO.getDealTimeStart()));
            }
            if (Objects.nonNull(pageVO.getDealTimeEnd())) {
                predicateList.add(cb.lessThanOrEqualTo(root.get("dealTime"), pageVO.getDealTimeEnd()));
            }
            if (StringUtils.isNotBlank(pageVO.getMemberName())) {
                predicateList.add(cb.like(root.get("memberName"), "%" + pageVO.getMemberName() + "%"));
            }

            Predicate[] p = new Predicate[predicateList.size()];
            return query.where(predicateList.toArray(p)).getRestriction();
        }, page);

        List<MemberReceiveTradeCommentPageVO> resultList = pageList.stream().map(e -> {
            MemberReceiveTradeCommentPageVO commentPageVO = new MemberReceiveTradeCommentPageVO();
            commentPageVO.setId(e.getId());
            commentPageVO.setStar(e.getStar());
            commentPageVO.setComment(e.getComment());
            commentPageVO.setProduct(e.getProduct());
            commentPageVO.setDealTime(e.getDealTime());
            commentPageVO.setMemberName(e.getMemberName());
            commentPageVO.setOrderNo(e.getOrderNo());
            commentPageVO.setPrice(e.getPrice());
            commentPageVO.setPurchaseCount(e.getDealCount());
            commentPageVO.setOrderId(e.getOrderId());
            commentPageVO.setStatus(e.getStatus());
            // 供应收到采购的评价可以回复, 采购收到的供应评价没有回复, 30天内可回复
            Integer replyStatus = MemberTradeTypeEnum.BUYER.getTypeEnum().equals(e.getTradeType())
                    && LocalDateTime.now().isBefore(e.getCreateTime().plusDays(30L))
                    && EnableDisableStatus.DISABLE.getCode().equals(e.getReplyStatus())
                    ? EnableDisableStatus.DISABLE.getCode() : EnableDisableStatus.ENABLE.getCode();
            commentPageVO.setReplyStatus(replyStatus);
            return commentPageVO;
        }).collect(Collectors.toList());

        return Wrapper.success(new PageData<>(pageList.getTotalElements(), resultList));
    }

    /**
     * 交易能力 - 会员评价管理 - 发出评价分页列表
     * 如果采购会员查看, 评价方角色是采购会员
     * 如果供应会员查看, 评价方角色是供应会员
     *
     * @param loginUser 登录用户信息
     * @param memberTradeTypeEnum 评价方角色枚举 1-供应会员，2-采购会员
     * @param pageVO 接口参数
     * @return 查询结果
     */
    @Override
    public Wrapper<PageData<MemberSendTradeCommentPageVO>> pageMemberSendTradeCommentHistory(UserLoginCacheDTO loginUser, MemberTradeTypeEnum memberTradeTypeEnum, MemberSendTradeCommentQueryVO pageVO) {
        Pageable page = PageRequest.of(pageVO.getCurrent() - 1, pageVO.getPageSize(), Sort.by("dealTime").descending());

        Page<MemberTradeCommentHistoryDO> pageList = memberTradeCommentHistoryRepository.findAll((Specification<MemberTradeCommentHistoryDO>) (root, query, cb) -> {
            List<Predicate> predicateList = new ArrayList<>();
            predicateList.add(cb.equal(root.get("memberId"), loginUser.getMemberId()));
            predicateList.add(cb.equal(root.get("roleId"), loginUser.getMemberRoleId()));
            predicateList.add(cb.equal(root.get("tradeType"), memberTradeTypeEnum.getTypeEnum()));
            if (Objects.nonNull(pageVO.getStar())) {
                predicateList.add(cb.equal(root.get("star"), pageVO.getStar()));
            }
            if (Objects.nonNull(pageVO.getDealTimeStart())) {
                predicateList.add(cb.greaterThanOrEqualTo(root.get("dealTime"), pageVO.getDealTimeStart()));
            }
            if (Objects.nonNull(pageVO.getDealTimeEnd())) {
                predicateList.add(cb.lessThanOrEqualTo(root.get("dealTime"), pageVO.getDealTimeEnd()));
            }
            if (StringUtils.isNotBlank(pageVO.getSubMemberName())) {
                predicateList.add(cb.like(root.get("subMemberName"), "%" + pageVO.getSubMemberName() + "%"));
            }

            Predicate[] p = new Predicate[predicateList.size()];
            return query.where(predicateList.toArray(p)).getRestriction();
        }, page);

        List<MemberSendTradeCommentPageVO> resultList = pageList.stream().map(e -> {
            MemberSendTradeCommentPageVO commentPageVO = new MemberSendTradeCommentPageVO();
            commentPageVO.setId(e.getId());
            commentPageVO.setStar(e.getStar());
            commentPageVO.setComment(e.getComment());
            commentPageVO.setProduct(e.getProduct());
            commentPageVO.setDealTime(e.getDealTime());
            commentPageVO.setSubMemberName(e.getSubMemberName());
            commentPageVO.setPrice(e.getPrice());
            commentPageVO.setPurchaseCount(e.getDealCount());
            commentPageVO.setOrderId(e.getOrderId());
            return commentPageVO;
        }).collect(Collectors.toList());

        return Wrapper.success(new PageData<>(pageList.getTotalElements(), resultList));
    }

    /**
     * 交易能力 - 采购会员评价管理 - 修改评价详情
     * @param tradeCommentSubmitVO 接口参数
     * @return 查询结果
     */
    @Override
    public Wrapper<Void> updateMemberTradeCommentHistory(MemberTradeCommentUpdateDetail tradeCommentSubmitVO) {
        MemberTradeCommentHistoryDO commentHistoryDO = memberTradeCommentHistoryRepository.findById(tradeCommentSubmitVO.getId()).orElse(null);
        if (Objects.isNull(commentHistoryDO)) {
            return Wrapper.fail(ResponseCode.MC_MS_COMMENT_NOT_FOUND);
        }

        // 敏感词过滤
        Wrapper<String> filterResult = platformManageFeignService.filterSensitiveWord(tradeCommentSubmitVO.getComment());
        if (filterResult.getCode() != ResponseCode.SUCCESS.getCode()) {
            return Wrapper.fail(filterResult.getCode(), filterResult.getMessage());
        }

        commentHistoryDO.setStar(tradeCommentSubmitVO.getStar());
        commentHistoryDO.setComment(filterResult.getData());
        commentHistoryDO.setPics(tradeCommentSubmitVO.getPics());

        memberTradeCommentHistoryRepository.saveAndFlush(commentHistoryDO);

        return Wrapper.success();
    }

    /**
     * 交易能力 - 评价管理 - 评价详情
     *
     * @param loginUser 登录用户信息
     * @param tradeCommentIdVO 接口参数
     * @return 查询结果
     */
    @Override
    public Wrapper<MemberTradeCommentDetailVO> getMemberTradeCommentHistory(UserLoginCacheDTO loginUser, MemberTradeCommentIdVO tradeCommentIdVO) {
        MemberTradeCommentHistoryDO commentHistoryDO = memberTradeCommentHistoryRepository.findById(tradeCommentIdVO.getId()).orElse(null);
        if (Objects.isNull(commentHistoryDO)) {
            return Wrapper.fail(ResponseCode.MC_MS_COMMENT_NOT_FOUND);
        }

        // 返回
        MemberTradeCommentDetailVO commentPageVO = new MemberTradeCommentDetailVO();
        commentPageVO.setId(commentHistoryDO.getId());
        commentPageVO.setMemberName(commentHistoryDO.getMemberName());
        commentPageVO.setStar(commentHistoryDO.getStar());
        commentPageVO.setComment(commentHistoryDO.getComment());
        commentPageVO.setProduct(commentHistoryDO.getProduct());
        commentPageVO.setOrderNo(commentHistoryDO.getOrderNo());
        commentPageVO.setOrderType(commentHistoryDO.getOrderType());
        commentPageVO.setDealTime(commentHistoryDO.getDealTime());
        commentPageVO.setPrice(commentHistoryDO.getPrice());
        commentPageVO.setTotalPrice(commentHistoryDO.getTotalPrice());
        commentPageVO.setPics(commentHistoryDO.getPics());
        commentPageVO.setProductImgUrl(commentHistoryDO.getProductImgUrl());
        commentPageVO.setPurchaseCount(commentHistoryDO.getDealCount());
        commentPageVO.setUnit(commentHistoryDO.getUnit());
        commentPageVO.setReplyContent(commentHistoryDO.getReplyContent());
        commentPageVO.setReplyTime(commentHistoryDO.getReplyTime());
        return Wrapper.success(commentPageVO);
    }

    /**
     * 商城能力 - 店铺渠道商城 - 现货商品详情 - 商户总体满意度
     * @param pageVO 接口参数
     * @return 查询结果
     */
    @Override
    public Wrapper<MemberDetailCreditCommentSummaryVO> pageOrderProductTradeCommentSummary(OrderProductTradeCommentVO pageVO) {
        MemberDetailCreditCommentSummaryVO summaryVO = new MemberDetailCreditCommentSummaryVO();

        List<MemberTradeCommentHistoryDO> historyDOList = memberTradeCommentHistoryRepository.findAll((Specification<MemberTradeCommentHistoryDO>) (root, query, cb) -> {
            List<Predicate> predicateList = new ArrayList<>();
            List<Integer> channelShopTypeList = Arrays.asList(ShopTypeEnum.CHANNEL.getCode(), ShopTypeEnum.CHANNEL_SCORE.getCode(), ShopTypeEnum.CHANNEL_SELF.getCode());
            if (channelShopTypeList.contains(pageVO.getShopType())) {
                // 渠道
                List<Integer> orderTypeList = Arrays.asList(
                        OrderTypeEnum.CHANNEL_STRAIGHT_MINING.getCode(),
                        OrderTypeEnum.CHANNEL_SPOT.getCode(),
                        OrderTypeEnum.CHANNEL_POINT_EXCHANGE.getCode()
                );
                predicateList.add(cb.equal(root.get("shopType"), pageVO.getShopType()));
                predicateList.add(cb.and(root.get("orderType").in(orderTypeList)));
            } else {
                // 非渠道
                List<Integer> orderTypeList = Arrays.asList(
                        OrderTypeEnum.INQUIRY_TO_PURCHASE.getCode(),
                        OrderTypeEnum.NEED_TO_PURCHASE.getCode(),
                        OrderTypeEnum.SPOT_PURCHASING.getCode(),
                        OrderTypeEnum.COLLECTIVE_PURCHASE.getCode(),
                        OrderTypeEnum.CREDITS_EXCHANGE.getCode()
                );
                predicateList.add(cb.and(root.get("orderType").in(orderTypeList)));
            }

            predicateList.add(cb.equal(root.get("status"), TradeCommentHistoryStatusEnum.SHOW.getCode()));
            predicateList.add(cb.equal(root.get("productId"), pageVO.getProductId()));
            predicateList.add(cb.equal(root.get("tradeType"), MemberTradeTypeEnum.BUYER.getTypeEnum()));
            Predicate[] p = new Predicate[predicateList.size()];
            return query.where(predicateList.toArray(p)).getRestriction();
        });

        //四舍五入计算平均星级
        double avgStarD = historyDOList.stream().mapToInt(MemberTradeCommentHistoryDO::getStar).average().orElse(0);
        Integer avgStar = Double.valueOf(Math.round(avgStarD)).intValue();
        summaryVO.setAvgStar(avgStar);

        //循环计算
        LocalDateTime last7days = LocalDateTime.now().minusDays(7);
        LocalDateTime last30days = LocalDateTime.now().minusDays(30);
        LocalDateTime last180days = LocalDateTime.now().minusDays(180);

        List<MemberDetailCreditCommentSummaryVO.TableRow> rows = Stream.of(5, 4, 3, 2, 1).map(star -> {
            MemberDetailCreditCommentSummaryVO.TableRow tableRow = new MemberDetailCreditCommentSummaryVO.TableRow();
            List<MemberTradeCommentHistoryDO> subList = historyDOList.stream().filter(h -> h.getStar().equals(star)).collect(Collectors.toList());

            long countIn7Days = subList.stream().filter(h -> h.getCreateTime().isAfter(last7days)).count();
            long countIn30Days = subList.stream().filter(h -> h.getCreateTime().isAfter(last30days)).count();
            long countIn180Days = subList.stream().filter(h -> h.getCreateTime().isAfter(last180days)).count();
            long countBefore180Days = subList.stream().filter(h -> h.getCreateTime().isBefore(last180days)).count();
            long sum = countIn180Days + countBefore180Days;

            tableRow.setStar(star);
            tableRow.setLast7days(countIn7Days);
            tableRow.setLast30days(countIn30Days);
            tableRow.setLast180days(countIn180Days);
            tableRow.setBefore180days(countBefore180Days);
            tableRow.setSum(sum);
            return tableRow;
        }).collect(Collectors.toList());

        summaryVO.setRows(rows);

        return Wrapper.success(summaryVO);
    }

    /**
     * 商城能力 - 店铺渠道商城 - 现货商品详情 - 交易评价分页列表(只显示采购商的评价)
     * @param pageVO 接口参数
     * @return 查询结果
     */
    @Override
    public Wrapper<PageData<ProductOrderTradeCommentPageVO>> pageOrderProductTradeCommentHistory(OrderProductTradeCommentQueryVO pageVO) {
        Pageable page = PageRequest.of(pageVO.getCurrent() - 1, pageVO.getPageSize(), Sort.by("createTime").ascending());

        final Integer allStarsLevel = 0;
        final Integer oneOrTwoStarsLevel = 1;
        final Integer threeStarsLevel = 2;

        Page<MemberTradeCommentHistoryDO> pageList = memberTradeCommentHistoryRepository.findAll((Specification<MemberTradeCommentHistoryDO>) (root, query, cb) -> {
            List<Predicate> predicateList = new ArrayList<>();
            List<Integer> channelShopTypeList = Arrays.asList(ShopTypeEnum.CHANNEL.getCode(), ShopTypeEnum.CHANNEL_SCORE.getCode(), ShopTypeEnum.CHANNEL_SELF.getCode());
            if (channelShopTypeList.contains(pageVO.getShopType())) {
                // 渠道
                List<Integer> orderTypeList = Arrays.asList(
                        OrderTypeEnum.CHANNEL_STRAIGHT_MINING.getCode(),
                        OrderTypeEnum.CHANNEL_SPOT.getCode(),
                        OrderTypeEnum.CHANNEL_POINT_EXCHANGE.getCode()
                );
                predicateList.add(cb.equal(root.get("shopType"), pageVO.getShopType()));
                predicateList.add(cb.and(root.get("orderType").in(orderTypeList)));
            } else {
                // 非渠道
                List<Integer> orderTypeList = Arrays.asList(
                        OrderTypeEnum.INQUIRY_TO_PURCHASE.getCode(),
                        OrderTypeEnum.NEED_TO_PURCHASE.getCode(),
                        OrderTypeEnum.SPOT_PURCHASING.getCode(),
                        OrderTypeEnum.COLLECTIVE_PURCHASE.getCode(),
                        OrderTypeEnum.CREDITS_EXCHANGE.getCode()
                );
                predicateList.add(cb.and(root.get("orderType").in(orderTypeList)));
            }

            predicateList.add(cb.equal(root.get("status"), TradeCommentHistoryStatusEnum.SHOW.getCode()));
            predicateList.add(cb.equal(root.get("productId"), pageVO.getProductId()));
            predicateList.add(cb.equal(root.get("tradeType"), MemberTradeTypeEnum.BUYER.getTypeEnum()));
            // startLevel不为空且不等于0
            if (Objects.nonNull(pageVO.getStarLevel()) && !allStarsLevel.equals(pageVO.getStarLevel())) {
                if (oneOrTwoStarsLevel.equals(pageVO.getStarLevel())) {
                    predicateList.add(cb.or(cb.equal(root.get("star").as(Integer.class), 1), cb.equal(root.get("star").as(Integer.class), 2)));
                } else if (threeStarsLevel.equals(pageVO.getStarLevel())) {
                    predicateList.add(cb.equal(root.get("star").as(Integer.class), 3));
                } else {
                    predicateList.add(cb.or(cb.equal(root.get("star").as(Integer.class), 4), cb.equal(root.get("star").as(Integer.class), 5)));
                }

            }

            Predicate[] p = new Predicate[predicateList.size()];
            return query.where(predicateList.toArray(p)).getRestriction();
        }, page);

        List<ProductOrderTradeCommentPageVO> resultList = pageList.stream().map(e -> {
            ProductOrderTradeCommentPageVO commentPageVO = new ProductOrderTradeCommentPageVO();
            commentPageVO.setId(e.getId());
            commentPageVO.setComment(e.getComment());
            commentPageVO.setStar(e.getStar());
            // 会员等级
            MemberRelationDO memberRelationDO = relationRepository.findFirstBySubMemberIdAndSubRoleIdAndRelType(e.getMemberId(), e.getRoleId(), MemberRelationTypeEnum.PLATFORM.getCode());
            commentPageVO.setLevelTag(memberRelationDO.getLevelRight().getLevelTag());
            commentPageVO.setMemberName(e.getMemberName());
            commentPageVO.setPics(e.getPics());
            commentPageVO.setCreateTime(e.getCreateTime());
            commentPageVO.setReplyContent(e.getReplyContent());
            return commentPageVO;
        }).collect(Collectors.toList());

        return Wrapper.success(new PageData<>(pageList.getTotalElements(), resultList));
    }

    /**
     * 交易能力 - 会员评价管理 - 交易评价汇总
     * 如果采购会员查看, 评价方角色是供应会员
     * 如果供应会员查看, 评价方角色是采购会员
     *
     * @param loginUser 登录用户信息
     * @return 查询结果
     */
    @Override
    public Wrapper<MemberDetailCreditCommentSummaryVO> getSubMemberTradeCommentSummary(UserLoginCacheDTO loginUser, MemberTradeTypeEnum memberTradeTypeEnum) {
        MemberDetailCreditCommentSummaryVO summaryVO = new MemberDetailCreditCommentSummaryVO();

        Specification<MemberTradeCommentHistoryDO> specification = (Specification<MemberTradeCommentHistoryDO>) (root, query, criteriaBuilder) -> {
            List<Predicate> list = new ArrayList<>();
            // 被评价会员id和角色id
            list.add(criteriaBuilder.equal(root.get("subMemberId").as(Long.class), loginUser.getMemberId()));
            list.add(criteriaBuilder.equal(root.get("subRoleId").as(Long.class), loginUser.getMemberRoleId()));
            list.add(criteriaBuilder.equal(root.get("tradeType"), memberTradeTypeEnum.getTypeEnum()));

            Predicate[] p = new Predicate[list.size()];
            return criteriaBuilder.and(list.toArray(p));
        };

        List<MemberTradeCommentHistoryDO> historyDOList = memberTradeCommentHistoryRepository.findAll(specification);

        //四舍五入计算平均星级
        double avgStarD = historyDOList.stream().mapToInt(MemberTradeCommentHistoryDO::getStar).average().orElse(0);
        Integer avgStar = Double.valueOf(Math.round(avgStarD)).intValue();
        summaryVO.setAvgStar(avgStar);

        //循环计算
        LocalDateTime last7days = LocalDateTime.now().minusDays(7);
        LocalDateTime last30days = LocalDateTime.now().minusDays(30);
        LocalDateTime last180days = LocalDateTime.now().minusDays(180);

        List<MemberDetailCreditCommentSummaryVO.TableRow> rows = Stream.of(5, 4, 3, 2, 1).map(star -> {
            MemberDetailCreditCommentSummaryVO.TableRow tableRow = new MemberDetailCreditCommentSummaryVO.TableRow();
            List<MemberTradeCommentHistoryDO> subList = historyDOList.stream().filter(h -> h.getStar().equals(star)).collect(Collectors.toList());

            long countIn7Days = subList.stream().filter(h -> h.getCreateTime().isAfter(last7days)).count();
            long countIn30Days = subList.stream().filter(h -> h.getCreateTime().isAfter(last30days)).count();
            long countIn180Days = subList.stream().filter(h -> h.getCreateTime().isAfter(last180days)).count();
            long countBefore180Days = subList.stream().filter(h -> h.getCreateTime().isBefore(last180days)).count();
            long sum = countIn180Days + countBefore180Days;

            tableRow.setStar(star);
            tableRow.setLast7days(countIn7Days);
            tableRow.setLast30days(countIn30Days);
            tableRow.setLast180days(countIn180Days);
            tableRow.setBefore180days(countBefore180Days);
            tableRow.setSum(sum);
            return tableRow;
        }).collect(Collectors.toList());

        summaryVO.setRows(rows);

        return Wrapper.success(summaryVO);
    }

    /**
     * 交易能力 - 会员评价管理 - 分页查询交易评论历史记录
     * 如果采购会员查看, 评价方角色是供应会员
     * 如果供应会员查看, 评价方角色是采购会员
     *
     * @param loginUser 登录用户信息
     * @param pageVO 接口参数
     * @return 查询结果
     */
    @Override
    public Wrapper<PageData<MemberDetailCreditTradeHistoryVO>> pageSubMemberTradeCommentHistory(UserLoginCacheDTO loginUser, MemberTradeTypeEnum memberTradeTypeEnum, MemberHistoryPageVO pageVO) {
        Pageable page = PageRequest.of(pageVO.getCurrent() - 1, pageVO.getPageSize(), Sort.by("dealTime").descending());

        //评价星级，1星或2星为差评，3星为中评，4星或5星为好评
        final Integer oneOrTwoStarsLevel = 1;
        final Integer threeStarsLevel = 2;

        Specification<MemberTradeCommentHistoryDO> specification = (Specification<MemberTradeCommentHistoryDO>) (root, query, criteriaBuilder) -> {
            List<Predicate> list = new ArrayList<>();
            // 被评价会员id和角色id
            list.add(criteriaBuilder.equal(root.get("subMemberId").as(Long.class), loginUser.getMemberId()));
            list.add(criteriaBuilder.equal(root.get("subRoleId").as(Long.class), loginUser.getMemberRoleId()));
            list.add(criteriaBuilder.equal(root.get("tradeType"), memberTradeTypeEnum.getTypeEnum()));

            if (pageVO.getStarLevel() != null) {
                if (pageVO.getStarLevel().equals(oneOrTwoStarsLevel)) {
                    list.add(criteriaBuilder.or(criteriaBuilder.equal(root.get("star").as(Integer.class), 1), criteriaBuilder.equal(root.get("star").as(Integer.class), 2)));
                } else if (pageVO.getStarLevel().equals(threeStarsLevel)) {
                    list.add(criteriaBuilder.equal(root.get("star").as(Integer.class), 3));
                } else {
                    list.add(criteriaBuilder.or(criteriaBuilder.equal(root.get("star").as(Integer.class), 4), criteriaBuilder.equal(root.get("star").as(Integer.class), 5)));
                }
            }

            Predicate[] p = new Predicate[list.size()];
            return criteriaBuilder.and(list.toArray(p));
        };

        Page<MemberTradeCommentHistoryDO> result = memberTradeCommentHistoryRepository.findAll(specification, page);

        return Wrapper.success(new PageData<>(result.getTotalElements(), result.getContent().stream().map(h -> {
            MemberDetailCreditTradeHistoryVO historyVO = new MemberDetailCreditTradeHistoryVO();
            historyVO.setId(h.getId());
            historyVO.setCreateTime(h.getCreateTime().format(ServiceConfig.DEFAULT_DATETIME_FORMATTER));
            historyVO.setDealTime(h.getDealTime().format(ServiceConfig.DEFAULT_DATETIME_FORMATTER));
            historyVO.setStar(h.getStar());
            historyVO.setByMemberName(h.getMemberName());
            historyVO.setComment(h.getComment());
            historyVO.setProduct(h.getProduct());
            historyVO.setOrderNo(h.getOrderNo());
            historyVO.setPrice(h.getPrice());
            historyVO.setPurchaseCount(h.getDealCount());
            historyVO.setOrderId(h.getOrderId());
            return historyVO;
        }).collect(Collectors.toList())));
    }

    /**
     * 交易能力-供应会员评价管理-收到评价-解释回复
     * @param loginUser 登录用户信息
     * @param memberTradeCommentSubmitVO 接口参数
     * @return 查询结果
     */
    @Override
    public Wrapper<Void> replyReceiveMemberTradeCommentHistory(UserLoginCacheDTO loginUser, MemberTradeReceiveCommentReplyVO memberTradeCommentSubmitVO) {
        MemberTradeCommentHistoryDO commentHistoryDO = memberTradeCommentHistoryRepository.findById(memberTradeCommentSubmitVO.getId()).orElse(null);
        if (Objects.isNull(commentHistoryDO)) {
            return Wrapper.fail(ResponseCode.MC_MS_COMMENT_NOT_FOUND);
        }
        // 采购会员评价的才能回复
        if (!MemberTradeTypeEnum.BUYER.getTypeEnum().equals(commentHistoryDO.getTradeType())) {
            return Wrapper.fail(ResponseCode.MC_MS_DATA_STATUS_INCORRECT_OPERATE_INVALID);
        }

        // 收到评价超过30天不能回复
        if (LocalDateTime.now().isAfter(commentHistoryDO.getCreateTime().plusDays(30L))) {
            return Wrapper.fail(ResponseCode.MC_MS_MEMBER_COMMENT_REPLY);
        }

        commentHistoryDO.setReplyStatus(EnableDisableStatus.ENABLE.getCode());
        commentHistoryDO.setReplyContent(memberTradeCommentSubmitVO.getContent());
        commentHistoryDO.setReplyTime(LocalDateTime.now());
        memberTradeCommentHistoryRepository.saveAndFlush(commentHistoryDO);

        return Wrapper.success();
    }

    /**
     * 交易能力-供应会员评价管理-收到评价-修改是否显示商品评价
     * @param updateVO 接口参数
     * @return 查询结果
     */
    @Override
    public Wrapper<Void> updateSupplyReceiveShowEvaluation(MemberTradeCommentUpdateStatusVO updateVO) {
        MemberTradeCommentHistoryDO memberTradeCommentHistoryDO = memberTradeCommentHistoryRepository.findById(updateVO.getId()).orElse(null);
        if (memberTradeCommentHistoryDO == null) {
            return Wrapper.fail(ResponseCode.MC_MS_COMMENT_NOT_FOUND);
        }
        memberTradeCommentHistoryDO.setStatus(updateVO.getStatus());
        memberTradeCommentHistoryRepository.save(memberTradeCommentHistoryDO);
        return Wrapper.success();
    }
}
